#pragma once

#include <cassert>
#include <cstddef>
#include <functional>
#include <utility>

/**
 * @brief 控制块结构：同时维护强引用计数（shared）与弱引用计数（weak）。
 *
 * strong_count == 拥有对象生命周期的 SharedPtr 数量；
 * weak_count   == 观察对象的 WearPtr 数量（不拥有对象）。
 *
 * 当 strong_count 降到 0 时，控制块负责销毁托管对象；
 * 当 strong_count == 0 且 weak_count == 0 时，控制块自身才会被释放。
 */
template <typename T>
struct ControlBlock {
    ControlBlock(T* ptr, std::function<void(T*)> deleter) noexcept
        : ptr(ptr), deleter(std::move(deleter)) {}

    /// 销毁托管对象（仅当 strong_count 归零时调用）
    void destroy_object() noexcept {
        if (ptr) {
            deleter(ptr);
            ptr = nullptr;
        }
    }

    T* ptr{nullptr};                       ///< 托管的裸指针
    std::size_t strong_count{1};          ///< 强引用计数（SharedPtr 数量）
    std::size_t weak_count{0};            ///< 弱引用计数（WearPtr 数量）
    std::function<void(T*)> deleter;      ///< 删除器
};

template <typename T> class SharedPtr;
template <typename T> class WearPtr;

/**
 * @brief 简化版 SharedPtr，实现共享所有权与引用计数。
 */
template <typename T>
class SharedPtr {
public:
    using element_type = T;

    /// 默认构造：空指针
    constexpr SharedPtr() noexcept = default;
    constexpr SharedPtr(std::nullptr_t) noexcept {}

    /**
     * @brief 从裸指针构造，使用默认 deleter（delete）。
     */
    explicit SharedPtr(T* ptr)
        : ptr_(ptr) {
        if (ptr_) {
            control_ = new ControlBlock<T>(
                ptr_,
                [](T* p) noexcept { delete p; }
            );
        }
    }

    /**
     * @brief 从裸指针 + 自定义删除器构造。
     */
    template <typename Deleter>
    SharedPtr(T* ptr, Deleter deleter)
        : ptr_(ptr) {
        if (ptr_) {
            control_ = new ControlBlock<T>(ptr_, std::move(deleter));
        }
    }

    /// 拷贝构造：共享控制块，强引用计数 +1
    SharedPtr(const SharedPtr& other) noexcept
        : ptr_(other.ptr_), control_(other.control_) {
        add_strong_ref();
    }

    /// 移动构造：转移控制权
    SharedPtr(SharedPtr&& other) noexcept
        : ptr_(other.ptr_), control_(other.control_) {
        other.ptr_ = nullptr;
        other.control_ = nullptr;
    }

    /// 从 WearPtr 锁定构造：若目标未过期，则共享控制块
    explicit SharedPtr(const WearPtr<T>& weak) {
        if (!weak.expired()) {
            ptr_ = weak.control_->ptr;
            control_ = weak.control_;
            add_strong_ref();
        }
    }

    /// 拷贝赋值
    SharedPtr& operator=(const SharedPtr& other) noexcept {
        if (this != &other) {
            release_strong();
            ptr_ = other.ptr_;
            control_ = other.control_;
            add_strong_ref();
        }
        return *this;
    }

    /// 移动赋值
    SharedPtr& operator=(SharedPtr&& other) noexcept {
        if (this != &other) {
            release_strong();
            ptr_ = other.ptr_;
            control_ = other.control_;
            other.ptr_ = nullptr;
            other.control_ = nullptr;
        }
        return *this;
    }

    ~SharedPtr() {
        release_strong();
    }

    void swap(SharedPtr& other) noexcept {
        std::swap(ptr_, other.ptr_);
        std::swap(control_, other.control_);
    }

    /// 重置为 nullptr
    void reset() noexcept {
        release_strong();
        ptr_ = nullptr;
        control_ = nullptr;
    }

    /// 重置为新指针（默认删除器）
    void reset(T* ptr) {
        reset();
        if (ptr) {
            control_ = new ControlBlock<T>(
                ptr,
                [](T* p) noexcept { delete p; }
            );
            ptr_ = ptr;
        }
    }

    /// 重置为新指针（自定义删除器）
    template <typename Deleter>
    void reset(T* ptr, Deleter deleter) {
        reset();
        if (ptr) {
            control_ = new ControlBlock<T>(ptr, std::move(deleter));
            ptr_ = ptr;
        }
    }

    T* get() const noexcept { return ptr_; }

    T& operator*() const noexcept {
        assert(ptr_ && "Dereferencing null SharedPtr");
        return *ptr_;
    }

    T* operator->() const noexcept {
        assert(ptr_ && "Accessing null SharedPtr");
        return ptr_;
    }

    std::size_t use_count() const noexcept {
        return control_ ? control_->strong_count : 0;
    }

    bool unique() const noexcept { return use_count() == 1; }

    explicit operator bool() const noexcept { return ptr_ != nullptr; }

private:
    friend class WearPtr<T>;

    void add_strong_ref() noexcept {
        if (control_) {
            ++control_->strong_count;
        }
    }

    void release_strong() noexcept {
        if (control_) {
            // strong 引用减 1
            if (--control_->strong_count == 0) {
                // 首先销毁对象
                control_->destroy_object();
                // 若无弱引用，释放控制块
                if (control_->weak_count == 0) {
                    delete control_;
                }
            }
            control_ = nullptr;
        }
        ptr_ = nullptr;
    }

    T* ptr_{nullptr};
    ControlBlock<T>* control_{nullptr};
};

/**
 * @brief 简化版 WearPtr（弱引用，不拥有对象），可通过 lock() 获得 SharedPtr。
 */
template <typename T>
class WearPtr {
public:
    using element_type = T;

    constexpr WearPtr() noexcept = default;
    constexpr WearPtr(std::nullptr_t) noexcept {}

    /// 由 SharedPtr 构造：共享控制块，弱引用计数 +1
    WearPtr(const SharedPtr<T>& shared) noexcept
        : control_(shared.control_) {
        if (control_) {
            add_weak_ref();
        }
    }

    /// 拷贝构造
    WearPtr(const WearPtr& other) noexcept
        : control_(other.control_) {
        add_weak_ref();
    }

    /// 移动构造
    WearPtr(WearPtr&& other) noexcept
        : control_(other.control_) {
        other.control_ = nullptr;
    }

    WearPtr& operator=(const WearPtr& other) noexcept {
        if (this != &other) {
            release_weak();
            control_ = other.control_;
            add_weak_ref();
        }
        return *this;
    }

    WearPtr& operator=(WearPtr&& other) noexcept {
        if (this != &other) {
            release_weak();
            control_ = other.control_;
            other.control_ = nullptr;
        }
        return *this;
    }

    ~WearPtr() {
        release_weak();
    }

    void swap(WearPtr& other) noexcept {
        std::swap(control_, other.control_);
    }

    void reset() noexcept {
        release_weak();
        control_ = nullptr;
    }

    /// 若未过期，则返回一个共享拥有权的 SharedPtr；否则返回空 SharedPtr。
    SharedPtr<T> lock() const noexcept {
        if (!expired()) {
            return SharedPtr<T>(*this);
        }
        return SharedPtr<T>();
    }

    bool expired() const noexcept {
        return !control_ || control_->strong_count == 0;
    }

    std::size_t use_count() const noexcept {
        return control_ ? control_->strong_count : 0;
    }

private:
    friend class SharedPtr<T>;

    void add_weak_ref() noexcept {
        if (control_) {
            ++control_->weak_count;
        }
    }

    void release_weak() noexcept {
        if (control_) {
            if (control_->weak_count > 0) {
                --control_->weak_count;
            }
            if (control_->strong_count == 0 && control_->weak_count == 0) {
                delete control_;
            }
            control_ = nullptr;
        }
    }

    ControlBlock<T>* control_{nullptr};
};

/**
 * @brief 简化版 make_shared：构造对象并返回 SharedPtr。
 */
template <typename T, typename... Args>
SharedPtr<T> make_shared(Args&&... args) {
    return SharedPtr<T>(new T(std::forward<Args>(args)...));
}